#pragma once
#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>
#include <queue>
#include <pthread.h>
#include <functional>
#include "Thread.hpp"

#include "Log.hpp"
using namespace log_ns;
using namespace ThreadMoudle;

static const int gdefaultnum = 5; // 默认线程数量

void test(string &str)
{
    while (true)
    {
        // cout << str << " helloworld" << endl;
        sleep(1);
    }
}

template <class T>
class ThreadPool
{
private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }

    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }

    void Wakeup() // 唤醒某个线程
    {
        pthread_cond_signal(&_cond);
    }
    void WakeupAll()
    { // 唤醒所有在等待的线程
        pthread_cond_broadcast(&_cond);
    }

    void Sleep() // 调用该函数的线程等待条件变量
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    bool IsEmpty()
    {
        return _task_queue.empty();
    }

    void HandlerTask(const string &name) // 线程池中线程的执行逻辑
    {
        while (true)
        {
            // 取任务
            LockQueue();
            while (IsEmpty() && _isrunning)
            {
                _sleep_thread_num++;
                Sleep();
                _sleep_thread_num--;
            }
            // 判断此时是否需要停止
            if (IsEmpty() && !_isrunning) // 此时没有任务且需要退出
            {
                // cout << name << " quit" << endl;
                UnlockQueue();
                break;
            }

            T t = _task_queue.front(); // 取出一个任务对象
            _task_queue.pop();
            UnlockQueue();
            t(); // 处理任务
            // cout << name << " : " << t.result() << endl;
        }
    }
    ThreadPool(int thread_num = gdefaultnum) // 初始化线程池
        : _thread_num(thread_num), _isrunning(false), _sleep_thread_num(0)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        LOG(1, "pthreadpool create successful!");
    }

public:
    void Init() // 初始化线程容器里的线程，赋予每个线程名字以及处理逻辑函数
    {
        func_t func = bind(&ThreadPool::HandlerTask, this, std::placeholders::_1); // 绑定HandlerTask函数的第一个参数
        for (int i = 0; i < _thread_num; i++)
        {
            string threadname = "thread-" + to_string(i + 1);
            _threads.emplace_back(threadname, func);
        }
    }
    // 单例模式下的资源访问点
    static ThreadPool<T> *GetInstance()
    {
        if (_tp == nullptr)
        {
            LockGuard lockguard(&_sig_mutex);
            if (_tp == nullptr)
            {
                LOG(INFO, "create threadpool!\n");
                _tp = new ThreadPool<T>();
                _tp->Init();
                _tp->Start();
            }
            else
            {
                LOG(INFO, "get threadpool\n");
            }
        }
        return _tp;
    }
    void Start() // 启动线程池里的所有线程，此时所有线程开始执行HandlerTask函数
    {
        _isrunning = true;
        for (auto &thread : _threads)
        {
            thread.Start();
        }
    }

    void Stop()
    {
        LockQueue();
        _isrunning = false;
        WakeupAll(); // 唤醒所有线程赶紧把剩下的任务处理了
        UnlockQueue();
    }

    void Push(const T &in)
    {
        LockQueue();
        if (_isrunning) // 如果线程池要停止，那就不要在生产任务了
        {
            _task_queue.push(in); // 生产了一个任务
            if (_sleep_thread_num > 0)
            {
                Wakeup(); // 唤醒一个等待的线程
            }
        }
        UnlockQueue();
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    int _thread_num;
    vector<Thread> _threads; // 线程组
    queue<T> _task_queue;    // 任务队列
    bool _isrunning;         // 运行状态
    int _sleep_thread_num;   // 休眠

    pthread_mutex_t _mutex;
    pthread_cond_t _cond; // 等待队列，没有收到任务的线程就等待
    // 单例模式
    static ThreadPool<T> *_tp;
    static pthread_mutex_t _sig_mutex;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::_tp = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::_sig_mutex = PTHREAD_MUTEX_INITIALIZER;